package api

import (
	"fmt"
	"github.com/gogf/gf/encoding/gbase64"
	"github.com/gogf/gf/frame/g"
	"github.com/gogf/gf/net/ghttp"
	"github.com/gogf/gf/os/gfile"
	"github.com/gogf/gf/os/glog"
	"github.com/gogf/gf/text/gstr"
	"go-middle/app/common/model/ci"
	"go-middle/app/common/model/ci_log"
	"go-middle/app/openapi/service/runner"
	"go-middle/library/mail"
	"go-middle/library/response"
	"net/url"
	"time"
)

//Runner 执行ci
func Runner(r *ghttp.Request) {
	j, err := r.GetJson()
	if err != nil {
		glog.Error("[ci]", err)
		response.StatusCode(r, 500, err.Error())
	}
	cloneUrl := j.GetString("repository.clone_url")
	ref := j.GetString("ref")
	branch := gstr.Replace(ref, "refs/heads/", "")
	ciTask, err := ci.Model.Where("branch=? and clone_url=? and status=1", branch, cloneUrl).FindOne()
	if err != nil {
		glog.Error("[ci]", err)
		response.StatusCode(r, 500, err.Error())
	}
	if ciTask == nil {
		response.StatusCode(r, 200, "无匹配的ci任务")
	}
	commit := j.GetString("after")
	ciLog := ci_log.Entity{
		CiId:      ciTask.Id,
		Title:     ciTask.Title,
		CloneUrl:  cloneUrl,
		Commit:    commit,
		Status:    0,
		Result:    "",
		StartTime: time.Now().Unix(),
	}
	res, err := ciLog.Insert()
	if err != nil {
		glog.Error("[ci]", err)
		response.StatusCode(r, 500, err.Error())
	}
	ciLog.Id, err = res.LastInsertId()
	if err != nil {
		glog.Error("[ci]", err)
		response.StatusCode(r, 500, err.Error())
	}
	//工作目录
	var projectHome string
	home := g.Config().GetString("ci.work_home")
	path := j.GetString("repository.path")
	if home[len(home)-1:] != "/" {
		projectHome = home + "/" + path
	} else {
		projectHome = home + path
	}
	if !gfile.Exists(home) {
		err = gfile.Mkdir(home)
		if err != nil {
			glog.Error("[ci]", err)
			response.StatusCode(r, 500, err.Error())
		}
	}
	go func(cl ci_log.Entity) {
		// 触发 执行
		var clone string
		var subject string
		if ciTask.IsClone == 1 {
			//clone
			if !gfile.Exists(projectHome) {
				tmp := gstr.Explode("://", cloneUrl)
				pwd64, err := gbase64.DecodeToString(ciTask.Password)
				if err != nil {
					glog.Error("[ci]", err)
				}
				pwd, err := runner.DeCrypt(pwd64)
				if err != nil {
					glog.Error("[ci]", err)
				}

				cloneUrlNew := fmt.Sprintf("%s://%s:%s@%s", tmp[0], url.QueryEscape(ciTask.User), pwd, tmp[1])
				clone = fmt.Sprintf(`cd %s; git clone %s;cd %s;`, home, cloneUrlNew, projectHome)
			} else {
				clone = fmt.Sprintf(`cd %s; git reset --hard ; git checkout %s; git pull;`, projectHome, branch)
			}
		}
		cmd := clone + ciTask.Command
		out, err := runner.RunShell(cmd, cloneUrl)
		cl.Result = fmt.Sprintf("执行命令:\n%s\n============\n执行结果:\n%s\n", ciTask.Command, out)
		if err != nil {
			cl.Result += err.Error() + "\n"
			cl.Status = 1
			subject = "[失败]"
		} else {
			cl.Status = 2
			subject = "[成功]"
		}
		//发送邮件通知
		if ciTask.NotifyEmail != "" {
			subject += fmt.Sprintf("%s[分支]%s", cl.Title, branch)
			err = mail.Send(subject, cl.Result, gstr.Explode(",", ciTask.NotifyEmail))
			if err != nil {
				errs := "[邮件]发送失败 " + err.Error()
				glog.Error(errs)
				cl.Result += fmt.Sprintf("============\n邮件通知:%s\n%s\n", "发送失败 "+err.Error(), ciTask.NotifyEmail)
			} else {
				cl.Result += fmt.Sprintf("============\n邮件通知:%s\n%s\n", "发送成功", ciTask.NotifyEmail)
			}
		}
		//更新日志
		cl.EndTime = time.Now().Unix()
		cl.RunTime = cl.EndTime - cl.StartTime
		_, err = cl.Update()
		if err != nil {
			errs := "[ci]执行结束,更新日志失败 " + err.Error()
			glog.Error(errs)
		}
	}(ciLog)
	response.StatusCode(r, 200, "success")
}
